﻿using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Contracts;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.Bill;
using Kingdee.BOS.JSON;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.ServiceHelper;
using Kingdee.BOS.Util;
using Kingdee.BOS.WebApi.FormService;
using Kingdee.K3.FIN.Core.Voucher;
using Newtonsoft.Json;
using RK.Model.Ronma;
using RK.Tools;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media.Media3D;

namespace RK.MySchedule.Ronma
{
    public class WorkflowSyncOA : IScheduleService
    {
        private Context context;
        public void Run(Context ctx, Schedule schedule)
        {
            this.context = ctx;
            string msg = "";
            string isremark = "0";
            string viewtype = "0";
            DynamicObjectCollection begRows = GetBegRows(context);
            foreach (var row in begRows)
            {
                isremark = "0";
                viewtype = "0";
                string[] receiverIds = Convert.ToString(row["FReceiverIds"]).Split(',');
                string formId = Convert.ToString(row["FOBJECTTYPEID"]);
                string keyValue = Convert.ToString(row["FKEYVALUE"]);
                string formName = Convert.ToString(row["FOBJECTTYPENAME"]);
                string billNo = Convert.ToString(row["fbillnumber"]);
                string assignId = Convert.ToString(row["FASSIGNID"]);
                foreach (var receiverId in receiverIds)
                {
                    string jsonStr = "";
                    DBResult result = new DBResult();
                    try
                    {
                        DynamicObject setting = KAndOSysSynTool.GetKToOSysSynSetting(context, "", 0);
                        if (setting == null)
                        {
                            msg = "获取同步设置和URL失败_appkey";
                        }
                        string appkey = Convert.ToString(setting["FOSysURL2"]);
                        DynamicObject order = KingdeeTools.GetDynamicObjectByFormIdAndId(context, formId, keyValue);
                        IBillView view = KingdeeTools.CreateBillView(context, formId);
                        view.Model.DataObject = order;
                        int creatorId = GetCreatorId(view);
                        string creator = KingdeeTools.GetCreator(context, creatorId);
                        string workcode = GetWorkCode(context, receiverId);
                        result = SyncToOA(row, appkey, result, context, setting, view, formId, out jsonStr, billNo, workcode, creator, isremark, viewtype);
                        msg = JsonConvert.SerializeObject(result);
                    }
                    catch (Exception er)
                    {
                        msg = er.Message;
                    }
                    finally
                    {
                        bool isOk = false;
                        //操作日志只记录一条
                        if (result.operResult == "1")
                        {
                            isOk = true;
                            string flag = "IsBeg";
                            string tablename = "T_WF_ASSIGN";
                            UpAssignIsSync(tablename, assignId, flag);
                            msg = string.Format("【{0}】{1}【{2}】成功，第三方系统返回信息：{3}！JSON信息：{4}", "定时任务beg", formName, billNo, msg, jsonStr);
                        }
                        else
                        {
                            msg = string.Format("【{0}】{1}【{2}】同步失败，第三方系统返回信息：{3}！JSON信息：{4}", "定时任务beg", formName, billNo, msg, jsonStr);
                        }
                        //记录日志
                        WriteLog(context, msg, jsonStr, isOk, formId, formName, billNo, assignId);
                    }
                }          
            }
            DynamicObjectCollection endRows = GetEndRows(context);
            foreach (var row in endRows)
            {
                isremark = "2";
                viewtype = "1";
                string[] receiverIds = Convert.ToString(row["FReceiverIds"]).Split(',');
                string formId = Convert.ToString(row["FOBJECTTYPEID"]);
                string keyValue = Convert.ToString(row["FKEYVALUE"]);
                string formName = Convert.ToString(row["FOBJECTTYPENAME"]);
                string billNo = Convert.ToString(row["fbillnumber"]);
                string assignId = Convert.ToString(row["FASSIGNID"]);
                foreach (var receiverId in receiverIds)
                {
                    string jsonStr = "";
                    DBResult result = new DBResult();
                    try
                    {
                        DynamicObject setting = KAndOSysSynTool.GetKToOSysSynSetting(context, "", 0);
                        if (setting == null)
                        {
                            msg = "获取同步设置和URL失败_appkey";
                        }
                        string appkey = Convert.ToString(setting["FOSysURL2"]);
                        DynamicObject order = KingdeeTools.GetDynamicObjectByFormIdAndId(context, formId, keyValue);
                        IBillView view = KingdeeTools.CreateBillView(context, formId);
                        view.Model.DataObject = order;
                        int creatorId = GetCreatorId(view);
                        string creator = KingdeeTools.GetCreator(context, creatorId);
                        string workcode = GetWorkCode(context, receiverId);
                        result = SyncToOA(row, appkey, result, context, setting, view, formId, out jsonStr, billNo, workcode, creator, isremark, viewtype);
                        msg = "workcode:" + workcode + ";" + JsonConvert.SerializeObject(result);
                    }
                    catch (Exception er)
                    {
                        msg = er.Message;
                    }
                    finally
                    {
                        bool isOk = false;
                        //操作日志只记录一条
                        if (result.operResult == "1")
                        {
                            string flag = "IsSync";
                            string tablename = "T_WF_ASSIGN";
                            isOk = true;
                            UpAssignIsSync(tablename, assignId, flag);
                            msg = string.Format("【{0}】{1}【{2}】成功，第三方系统返回信息：{3}！JSON信息：{4}", "定时任务end", formName, billNo, msg, jsonStr);
                        }
                        else
                        {
                            msg = string.Format("【{0}】{1}【{2}】同步失败，第三方系统返回信息：{3}！JSON信息：{4}", "定时任务end", formName, billNo, msg, jsonStr);
                        }
                        //记录日志
                        WriteLog(context, msg, jsonStr, isOk, formId, formName, billNo, assignId);
                    }
                }
            }
        }

        private DynamicObjectCollection GetEndRows(Context context)
        {
            string sql = string.Format(@"/*dialect*/ 
            SELECT T6.FASSIGNNAME, 
                   T0.FASSIGNID, 
                   T0.FSTATUS, 
                   T0.FSENDERID, 
                   T1.FNUMBER, 
                   LEFT(T1.FNUMBER, (CHARINDEX('_', T1.FNUMBER) - 1)) fbillnumber, 
                   T1.FTMPID, 
                   T2.FOBJECTTYPEID, 
                   T0.FRECEIVERNAMES FReceiverIds, 
                   T4.FNAME FOBJECTTYPENAME, 
                   T3.FKEYVALUE, 
                   T5.FORGID
            FROM T_WF_ASSIGN T0
                 LEFT JOIN T_WF_PROCINST T1 ON T1.FPROCINSTID = T0.FPROCINSTID
                 LEFT OUTER JOIN T_WF_PIBIMAP T2 ON T0.FPROCINSTID = T2.FPROCINSTID
                 LEFT JOIN T_WF_APPROVALASSIGN T3 ON T3.FASSIGNID = T0.FASSIGNID
                 LEFT JOIN T_META_OBJECTTYPE_L T4 ON T4.FID = T2.FOBJECTTYPEID
                 LEFT JOIN T_WF_TEMPLATE T5 ON T5.FTMPID = T1.FTMPID
                 LEFT JOIN T_WF_ASSIGN_L T6 ON T6.FASSIGNID = T0.FASSIGNID
                                               AND T6.FLOCALEID = 2052
                 LEFT JOIN T_WF_RECEIVER T7 ON T7.FASSIGNID = T0.FASSIGNID
            WHERE T0.FCREATETIME >= '2024-11-07 10:49:00.600'
                  AND T0.FSTATUS = 1 AND T0.IsSync=0
                  AND T2.FOBJECTTYPEID IN('k0029a25e1d914fe39bf425b172895008', 'YCVN_JDSCTLSQD', 'ke2d08362c2eb4bf9aa8aa74e740d1740', 'YCVN_SCBLD', 'PRD_ReturnMtrl', 'PRD_INSTOCK', 'PRD_MORPT', 'PRD_FeedMtrl', 'STK_OEMInStockRETURN', 'STK_OEMInStock', 'STK_OEMReceive', 'ENG_ECNOrder', 'PRD_ISSUEMTRNOTICE', 'CN_CASHACCESSBILL', 'PRD_MOVEMTRL', 'PRD_PickMtrl', 'PRD_MO', 'ENG_BOM', 'PRD_RetStock', 'PRD_PPBOM', 'SAL_BATCHADJUSTPRICE', 'BD_SAL_PriceList', 'STK_MisDelivery', 'SAL_SaleOrder', 'STK_TransferDirect', 'STK_MISCELLANEOUS', 'STK_InStock', 'PLN_FORECAST', 'SUB_SUBREQORDER', 'PLN_PLANORDER', 'SUB_FEEDMTRL', 'STK_TRANSFERAPPLY', 'IV_PUREXVATIN', 'SAL_RETURNSTOCK', 'PUR_MRB', 'PUR_MRAPP', 'CN_BANKTRANSBILL', 'AP_OtherPayable', 'AR_RECEIVEBILL', 'AP_REFUNDBILL', 'AR_REFUNDBILL', 'AP_Payable', 'SAL_OUTSTOCK', 'AR_receivable', 'IV_SALESIC', 'IV_PURCHASEIC', 'PUR_ReceiveBill', 'SUB_PickMtrl', 'AP_PAYBILL', 'CN_PAYAPPLY') ");
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(context, sql);
            return doc;
        }

        private void WriteLog(Context context, string msg, string jsonStr, bool isOk, string formId, string formName, string billNo, string assignId)
        {
            SyncLog log = new SyncLog();
            log.Operation = "定时任务";
            log.FormId = formId;
            log.FbillName = formName;
            log.FBillNo = billNo;
            log.Result = msg;
            log.FOrgId = 0;
            log.Direction = assignId;
            log.Json = jsonStr;
            log.IsSuccess = isOk;
            KingdeeTools.SaveLog(context, log);
        }

        private void UpAssignIsSync(string tablename, string assignId, string flag)
        {
            string sql = string.Format($"/*dialect*/ UPDATE T0 SET T0.{flag}=1 FROM {tablename} T0 WHERE T0.FASSIGNID='{assignId}' ");
            DBServiceHelper.Execute(context, sql);
        }

        private DBResult SyncToOA(DynamicObject row, string appkey, DBResult result, Context context, DynamicObject setting, IBillView view, string formId, out string jsonStr, string billNo, string workcode, string creator, string isremark, string viewtype)
        {
            List<DynamicObject> kToOSysSynOps = KAndOSysSynTool.GetKToOSysSynOps(context, formId, 0, "Submit", 2, "1");
            DynamicObject kToOSysSynOp = GetSatisfyConditionOp(view, kToOSysSynOps, "提交");
            string port = Convert.ToString(kToOSysSynOp["Port"]);
            string url = KAndOSysSynTool.GetUrl(setting, port);
            //节点ID
            string AssignId = Convert.ToString(row["FASSIGNID"]);
            //节点名称
            string ActivityName = Convert.ToString(row["FASSIGNNAME"]);
            //单据名称
            string formName = Convert.ToString(row["FOBJECTTYPENAME"]);
            string curFlowId = formName + AssignId;
            string timestamp = GetTimestamp();
            JSONObject cJson = new JSONObject();
            cJson.Add("syscode", "ERP");
            cJson.Add("flowid", curFlowId);
            cJson.Add("requestname", $"{creator}发起的{formName}:{billNo}审批流需要您处理！");
            //cJson.Add("requestname", chartActionInfo.Title);
            cJson.Add("workflowname", $"{formName}审批流");
            cJson.Add("nodename", ActivityName);
            cJson.Add("receiver", workcode);
            cJson.Add("creator", creator);
            cJson.Add("createdatetime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            cJson.Add("receivedatetime", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            cJson.Add("appurl", AssignId);
            cJson.Add("pcurl", AssignId);
            cJson.Add("receivets", timestamp);
            cJson.Add("isremark", isremark);
            cJson.Add("viewtype", viewtype);
            jsonStr = cJson.ToString();
            result = InvokeHelper.Post(url, jsonStr, appkey, workcode, 0);
            return result;
        }

        private string GetTimestamp()
        {
            // 获取当前时间
            DateTime currentTime = DateTime.UtcNow;

            // Unix时间戳起始时间
            DateTime unixStartTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

            // 计算当前时间与Unix起始时间的时间间隔
            TimeSpan elapsedTime = currentTime - unixStartTime;

            // 将时间间隔的总秒数作为Unix时间戳
            //long timestamp = (long)elapsedTime.TotalSeconds;
            long timestamp = (long)elapsedTime.TotalMilliseconds;
            return timestamp.ToString();
        }

        private DynamicObject GetSatisfyConditionOp(IBillView view, List<DynamicObject> kToOSysSynOps, string OperationName)
        {
            //只有一个同步操作，且前置条件为空
            if (kToOSysSynOps.Count() == 1 && kToOSysSynOps.First()["FPrecondition"].IsNullOrEmptyOrWhiteSpace())
            {
                return kToOSysSynOps.First();
            }
            List<DynamicObject> successObjs = new List<DynamicObject>();
            //存在多个同步操作，循环所有
            foreach (var kToOSysSynOp in kToOSysSynOps)
            {
                string pyExpression = Convert.ToString(kToOSysSynOp["FPrecondition"]);
                var result = KAndOSysSynTool.analysisConditionalExpression(view, 0, "", pyExpression);
                bool isSuccess = false;
                Boolean.TryParse(Convert.ToString(result), out isSuccess);
                if (isSuccess)
                {
                    successObjs.Add(kToOSysSynOp);
                }
            }
            if (successObjs.Count() == 1)
            {
                return successObjs.First();
            }
            else if (successObjs.Count() > 1)
            {
                List<string> errs = new List<string>();
                foreach (var successObj in successObjs)
                {
                    string id = Convert.ToString(successObj["id"]);
                    string pyExpression = Convert.ToString(successObj["FPrecondition"]);
                    string err = string.Format("【{0}】前置条件【{1}】", id, pyExpression);
                    errs.Add(err);
                }
                string errMsg = string.Format("获取到{0}【{1}】有效操作设置有多个：{2}"
                    , view.BusinessInfo.GetForm().Name
                    , OperationName
                    , string.Join(",\r\n", errs)
                    ); ;
                throw new Exception(errMsg);
            }
            else
            {
                return null;
            }
        }

        private string GetWorkCode(Context context, string receiverId)
        {
            string workcode = "";
            var res = WebApiServiceCall.ExecuteBillQuery(context, QueryParameter("SEC_User", "F_YCVN_GH", $"fname='{receiverId}'"));
            if (res.Count > 0)
            {
                workcode = res.FirstOrDefault().FirstOrDefault().ToString();
            }
            return workcode;
        }

        private string QueryParameter(string formId, string fieldKeys, string filterString)
        {
            var param = new
            {
                FormId = formId,
                FieldKeys = fieldKeys,
                FilterString = filterString
            };
            return JsonConvert.SerializeObject(param);
        }

        private int GetCreatorId(IBillView view)
        {
            int creatorId = 0;// 
            if (view.Model.DataObject.Contains("CreatorId"))
            {
                DynamicObject userObj = view.Model.DataObject["CreatorId"] as DynamicObject;
                creatorId = userObj == null ? 0 : Convert.ToInt32(userObj["Id"]);
            }
            else
            {
                if (view.Model.DataObject.Contains("FCreatorId"))
                {
                    DynamicObject userObj = view.Model.DataObject["FCreatorId"] as DynamicObject;
                    creatorId = userObj == null ? 0 : Convert.ToInt32(userObj["Id"]);
                }
            }
            if (view.Model.DataObject.Contains("FCreaterId"))
            {
                DynamicObject userObj = view.Model.DataObject["FCreaterId"] as DynamicObject;
                creatorId = userObj == null ? 0 : Convert.ToInt32(userObj["Id"]);
            }
            return creatorId;
        }

        /// <summary>
        /// 获取初始状态的流程
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private DynamicObjectCollection GetBegRows(Context context)
        {
            string sql = string.Format(@"/*dialect*/ 
            SELECT T6.FASSIGNNAME, 
                   T0.FASSIGNID, 
                   T0.FSTATUS, 
                   T0.FSENDERID, 
                   T1.FNUMBER, 
                   LEFT(T1.FNUMBER, (CHARINDEX('_', T1.FNUMBER) - 1)) fbillnumber, 
                   T1.FTMPID, 
                   T2.FOBJECTTYPEID, 
                   T0.FRECEIVERNAMES FReceiverIds, 
                   T4.FNAME FOBJECTTYPENAME, 
                   T3.FKEYVALUE, 
                   T5.FORGID, 
                   T7.FRECEIVERID
            FROM T_WF_ASSIGN T0
                 LEFT JOIN T_WF_PROCINST T1 ON T1.FPROCINSTID = T0.FPROCINSTID
                 LEFT OUTER JOIN T_WF_PIBIMAP T2 ON T0.FPROCINSTID = T2.FPROCINSTID
                 LEFT JOIN T_WF_APPROVALASSIGN T3 ON T3.FASSIGNID = T0.FASSIGNID
                 LEFT JOIN T_META_OBJECTTYPE_L T4 ON T4.FID = T2.FOBJECTTYPEID
                 LEFT JOIN T_WF_TEMPLATE T5 ON T5.FTMPID = T1.FTMPID
                 LEFT JOIN T_WF_ASSIGN_L T6 ON T6.FASSIGNID = T0.FASSIGNID
                                               AND T6.FLOCALEID = 2052
                 LEFT JOIN T_WF_RECEIVER T7 ON T7.FASSIGNID = T0.FASSIGNID
            WHERE T0.FCREATETIME >= '2024-11-07 10:49:00.600'
                  AND T0.IsBeg = 0
                  AND T0.FSTATUS = 0
                  AND T2.FOBJECTTYPEID IN('k0029a25e1d914fe39bf425b172895008', 'YCVN_JDSCTLSQD', 'ke2d08362c2eb4bf9aa8aa74e740d1740', 'YCVN_SCBLD', 'PRD_ReturnMtrl', 'PRD_INSTOCK', 'PRD_MORPT', 'PRD_FeedMtrl', 'STK_OEMInStockRETURN', 'STK_OEMInStock', 'STK_OEMReceive', 'ENG_ECNOrder', 'PRD_ISSUEMTRNOTICE', 'CN_CASHACCESSBILL', 'PRD_MOVEMTRL', 'PRD_PickMtrl', 'PRD_MO', 'ENG_BOM', 'PRD_RetStock', 'PRD_PPBOM', 'SAL_BATCHADJUSTPRICE', 'BD_SAL_PriceList', 'STK_MisDelivery', 'SAL_SaleOrder', 'STK_TransferDirect', 'STK_MISCELLANEOUS', 'STK_InStock', 'PLN_FORECAST', 'SUB_SUBREQORDER', 'PLN_PLANORDER', 'SUB_FEEDMTRL', 'STK_TRANSFERAPPLY', 'IV_PUREXVATIN', 'SAL_RETURNSTOCK', 'PUR_MRB', 'PUR_MRAPP', 'CN_BANKTRANSBILL', 'AP_OtherPayable', 'AR_RECEIVEBILL', 'AP_REFUNDBILL', 'AR_REFUNDBILL', 'AP_Payable', 'SAL_OUTSTOCK', 'AR_receivable', 'IV_SALESIC', 'IV_PURCHASEIC', 'PUR_ReceiveBill', 'SUB_PickMtrl', 'AP_PAYBILL', 'CN_PAYAPPLY') ");
            DynamicObjectCollection doc = DBUtils.ExecuteDynamicObject(context, sql);
            return doc;
        }
    }
}
